package cn.wp.ewallet.wallet.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.wp.ewallet.common.extension.properties.EthProperties;
import cn.wp.ewallet.wallet.extension.constant.EwalletWalletConstant;
import cn.wp.ewallet.wallet.extension.util.EwalleTransactionUtil;
import cn.wp.ewallet.wallet.model.dto.WalletAccountInfoDto;
import cn.wp.ewallet.wallet.model.entity.WalletInfoDo;
import cn.wp.ewallet.wallet.service.AccountInfoService;
import cn.wp.ewallet.wallet.service.SyncAssetsService;
import cn.wp.ewallet.wallet.service.WalletInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.web3j.protocol.Web3j;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;

import static cn.wp.ewallet.wallet.extension.constant.EwalletWalletConstant.ACCOUNT_TYPE_WEB;

/**
 * 资产同步服务
 * Created by zhangyongli on 2020/2/6
 */
@Slf4j
@Service
public class SyncAssetsServiceImpl implements SyncAssetsService {

    @Autowired
    private WalletInfoService walletInfoService;

    @Autowired
    private AccountInfoService accountInfoService;

    @Autowired
    private EthProperties ethProperties;

    @Override
    public void execute() {

        //查询所有钱包信息
        List<WalletInfoDo> list = walletInfoService.getAllByWalletType();
        if (null == list) {
            return;
        }
        EwalleTransactionUtil walleUtil = EwalleTransactionUtil.getInstance();
        //连接web3j
        Web3j web3j = walleUtil.getDefaultConect(ethProperties.getNetwork());

        //循环同步资产
        for (WalletInfoDo wa: list) {
            syncAssets(wa, web3j, walleUtil);
        }
    }

    /**
     * 同步账户资产
     * @param wa
     * @param web3j
     * @param walleUtil
     */
    private void syncAssets(WalletInfoDo wa, Web3j web3j, EwalleTransactionUtil walleUtil) {

        //查询地址全部账户信息
        List<WalletAccountInfoDto> list = walletInfoService.getAllWalletAccountByAddress(wa.getWalletAddress());
        if (CollectionUtil.isEmpty(list)) {
            log.error("地址无账户信息，地址={}", wa.getWalletAddress());
            return;
        }

        //链上资产账户
        List<WalletAccountInfoDto> wList = list.stream().filter(item -> EwalletWalletConstant.ACCOUNT_TYPE_WEB.equals(item.getAccoutType())).collect(Collectors.toList());

        try {
            if (CollectionUtil.isNotEmpty(wList)) {
                for (WalletAccountInfoDto dto : wList) {
                    //查询token余额
                    BigInteger tokenBlance = walleUtil.getTokenBalance(web3j, wa.getWalletAddress(), dto.getContractAddress());
                    if (tokenBlance.compareTo(BigInteger.valueOf(0)) > 0) {
                        BigInteger newBlance = tokenBlance.subtract(dto.getMoneyAmount().toBigInteger());
                        //保存可用资产账户变动信息
                        accountInfoService.saveAccountChange(wa.getWalletAddress(), new BigDecimal(newBlance), EwalletWalletConstant.ACCOUNT_ADD, EwalletWalletConstant.ACCOUNT_CHARGE_CASE_CHANGE_INTO, dto.getMoneyTypeId(), EwalletWalletConstant.ACCOUNT_TYPE_AVAILABLE);
                        //保存资产账户变动信息
                        accountInfoService.saveAccountChange(wa.getWalletAddress(), new BigDecimal(newBlance), EwalletWalletConstant.ACCOUNT_ADD, EwalletWalletConstant.ACCOUNT_CHARGE_CASE_CHANGE_INTO, dto.getMoneyTypeId(), EwalletWalletConstant.ACCOUNT_TYPE_WEB);
                    }
                    log.info("链上资产同步完成，地址={}，token数量={}", wa.getWalletAddress(), tokenBlance);
                }

            }else {
                log.info("地址无链上资产账户，已重新创建，地址={}", wa.getWalletAddress());
                //创建USDT账户-链上资产账户
                accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_USDT, EwalletWalletConstant.ACCOUNT_NAME_USDT+"-链上资产", wa.getWalletAddress(), ACCOUNT_TYPE_WEB);

                //创建SHQC账户-链上资产账户
                accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_SHQC, EwalletWalletConstant.ACCOUNT_NAME_SHQC+"-链上资产", wa.getWalletAddress(), ACCOUNT_TYPE_WEB);
            }
        } catch (IOException e) {
            log.error("链上资产同步失败，地址={}", wa.getWalletAddress());
            e.printStackTrace();
        }
    }
}
